package com.wiscamp.ninechapters.tags.domain.services;

import com.wiscamp.ninechapters.tags.domain.TagsErrorCodes;
import com.wiscamp.ninechapters.tags.domain.models.Tag;
import com.wiscamp.ninechapters.tags.domain.repositories.TagRepository;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.BaseDomainService;
import cube.ddd.exception.ExceptionUtils;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * Tag Service
 *
 * @author yifeng
 */
@Service
public class TagService extends BaseDomainService {

    private final TagRepository tagRepository;

    private final String CACHE_NAME = "tags";

    public TagService(TagRepository tagRepository) {
        this.tagRepository = tagRepository;
    }


    // region tag
    @Cacheable(value = CACHE_NAME, key = "#tagId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public Tag getTag(@Min(0) long tagId) {
        var tag = tagRepository.getTag(tagId);
        if (Objects.isNull(tag)) {
            ExceptionUtils.throwServiceException(TagsErrorCodes.TAG_NOT_FOUND, tagId);
        }
        return tag;
    }

    /*@HandleServiceException
    public Tag getTagByCode(@NotBlank String code, long appId) {
        return tagRepository.getTagByCode(code, appId);
    }

    @Cacheable(value = "tags:name", key = "T(String).valueOf(#groupName).concat('-').concat(#tagName)",
            cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public Tag getTagByName(@NotBlank String groupName, @NotBlank String tagName, long appId) {
        return tagRepository.getTagByName(groupName, tagName, appId);
    }

    @Cacheable(value = "tags:groupName", key = "#groupName",
            cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public Collection<Tag> getTagsByGroupName(@NotBlank String groupName, long appId) {
        return tagRepository.getTagsByGroupName(groupName, appId);
    }

    @HandleServiceException
    public Collection<Tag> getTagsByIds(@NotBlank Collection<Long> tagIds) {
        return tagRepository.getTagsByIds(tagIds);
    }*/

    @CachePut(value = CACHE_NAME, key = "#tag.tagId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public Tag createTag(@NotNull Tag tag, long operatorId) {
        var existedTag = tagRepository.getTagByCode(tag.getTagCode(), tag.getApplicationId());
        if (Objects.nonNull(existedTag)) {
            ExceptionUtils.throwServiceException(TagsErrorCodes.TAG_CODE_EXISTED, tag);
        }
        tag.createBy(operatorId);
        return tagRepository.saveTag(tag);
    }

    @CachePut(value = CACHE_NAME, key = "#tag.tagId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public Tag updateTag(@NotNull Tag tag, long operatorId) {
        var existedTag = getTag(tag.getTagId());
        existedTag = tagRepository.getTagByCode(tag.getTagCode(), tag.getApplicationId());
        if (Objects.nonNull(existedTag) && existedTag.getTagId() != tag.getTagId()) {
            ExceptionUtils.throwServiceException(TagsErrorCodes.TAG_CODE_EXISTED, tag);
        }
        tag.updateBy(operatorId);
        return tagRepository.saveTag(tag);
    }

    @CacheEvict(value = CACHE_NAME, key = "#tagId")
    @HandleServiceException
    public boolean deleteTag(@Min(0) long tagId, long operatorId) {
        var tag = getTag(tagId);
        if (Objects.isNull(tag)) return false;
        // 记录操作日志
        tag.delete();
        tag.updateBy(operatorId);
        tagRepository.saveTag(tag);
        return true;
    }

    @CacheEvict(value = CACHE_NAME, key = "#tagId")
    @HandleServiceException
    public boolean enableTag(@Min(0) long tagId, long operatorId) {
        var tag = getTag(tagId);
        if (Objects.isNull(tag)) return false;
        // 记录操作日志
        tag.enable();
        tag.updateBy(operatorId);
        tagRepository.saveTag(tag);
        return true;
    }

    @CacheEvict(value = CACHE_NAME, key = "#tagId")
    @HandleServiceException
    public boolean disableTag(@Min(0) long tagId, long operatorId) {
        var tag = getTag(tagId);
        if (Objects.isNull(tag)) return false;
        // 记录操作日志
        tag.disable();
        tag.updateBy(operatorId);
        tagRepository.saveTag(tag);
        return true;
    }
    //endregion

}
